package com.mths.server.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.mths.client.controller.DocumentController;
import com.mths.client.dto.DocClassDTO;
import com.mths.client.dto.DocMetaSaveDTO;
import com.mths.client.dto.DocMetaSearchDTO;
import com.mths.client.dto.DocTypeDTO;
import com.mths.client.dto.MetaDataDTO;
import com.mths.client.dto.MetaParamDTO;
import com.mths.client.util.ListItem;
import com.mths.server.dao.DocumentMetaDAO;
import com.mths.server.dao.DocumentTypeDAO;
import com.mths.server.dao.MetaDataDAO;
import com.mths.server.entity.DocumentMetaData;
import com.mths.server.entity.DocumentType;
import com.mths.server.entity.MetaData;
import com.mths.server.entity.MetaDataParam;

/**
 * The server side implementation of the RPC service.
 */
@Service("documentController")
@Transactional
public class DocumentControllerImpl extends AbstractController implements DocumentController {

	@Autowired
	private transient MetaDataDAO metaDataDAO;

	@Autowired
	private transient DocumentTypeDAO documentTypeDAO;

	@Autowired
	private transient DocumentMetaDAO documentMetaDAO;

	@Override
	public void saveMetaData(MetaDataDTO dto) {

		MetaData metaData = null;
		// control is update
		if (!StringUtils.isEmpty(dto.getObjid())) {
			metaData = metaDataDAO.findByOid(dto.getObjid());
		}
		if (metaData == null)
			metaData = new MetaData();

		metaData.setObjid(dto.getObjid());
		metaData.setFieldName(dto.getFieldName());
		metaData.setFieldId(dto.getFieldId());
		metaData.setFieldType(dto.getFieldType());
		metaData.setFieldOrder(dto.getFieldOrder());
		metaDataDAO.persistOrUpdate(metaData);
	}

	@Override
	public List<MetaDataDTO> loadMetaDatas(MetaDataDTO dto) {
		List<MetaDataDTO> metadaList = new ArrayList<MetaDataDTO>();
		List<MetaData> metaList = metaDataDAO.findAll();
		if (metaList != null) {
			for (MetaData metaData : metaList) {
				metadaList.add(new MetaDataDTO(metaData.getObjid(), metaData.getFieldId(), metaData.getFieldType(),
						metaData.getFieldName(), metaData.getFieldOrder()));
			}
		}
		return metadaList;
	}

	@Override
	public List<ListItem> loadMetaDataTypeCombo(String arg) {
		return metaDataDAO.findMetaDataTypeCombo();
	}

	@Override
	public void saveMetaParam(MetaParamDTO dto) {
		MetaDataParam metaDataParam = null;
		// control is update
		if (!StringUtils.isEmpty(dto.getObjid())) {
			metaDataParam = metaDataDAO.findMetaParamByOid(dto.getObjid());
		}
		if (metaDataParam == null)
			metaDataParam = new MetaDataParam();

		metaDataParam.setObjid(dto.getObjid());
		metaDataParam.setParamKey(dto.getKey());
		metaDataParam.setParamValue(dto.getValue());
		metaDataParam.setMetaData(metaDataDAO.findByOid(dto.getMetaDataOid()));
		metaDataDAO.persistOrUpdateParam(metaDataParam);

	}

	@Override
	public List<MetaParamDTO> loadMetaParamList(String metaOid) {
		return metaDataDAO.findMetaParamList(metaOid);
	}

	@Override
	public void saveDocClass(DocClassDTO dto) {

		DocumentType documentType = null;
		// control is update
		if (!StringUtils.isEmpty(dto.getObjid())) {
			documentType = documentTypeDAO.findByOid(dto.getObjid());
		}
		if (documentType == null)
			documentType = new DocumentType();

		documentType.setObjid(dto.getObjid());
		documentType.setName(dto.getDocClassName());
		documentTypeDAO.persistOrUpdate(documentType);
	}

	@Override
	public List<DocClassDTO> loadDocClassTable(DocClassDTO dto) {
		List<DocClassDTO> docClassList = new ArrayList<DocClassDTO>();
		List<DocumentType> docList = documentTypeDAO.loadAllDocClass();
		if (docList != null) {
			for (DocumentType docType : docList) {
				docClassList.add(new DocClassDTO(docType.getObjid(), docType.getName()));
			}
		}
		return docClassList;
	}

	@Override
	@Transactional
	public DocMetaSearchDTO loadDocMetaDataList(String docTypeOid) throws Exception {
		if (StringUtils.isEmpty(docTypeOid))
			throw new Exception("Document objid can not be null");

		List<DocumentMetaData> docMetaList = documentMetaDAO.loadByDocTypeOid(docTypeOid);
		List<MetaData> metaList = metaDataDAO.findAll();
		DocMetaSearchDTO documentMetaDTO = new DocMetaSearchDTO();

		if (docMetaList != null) {
			for (DocumentMetaData docMeta : docMetaList) {
				MetaData metaData = docMeta.getMetaData();
				documentMetaDTO.getDocReleatedMetaList().add(
						new MetaDataDTO(metaData.getObjid(), metaData.getFieldId(), metaData.getFieldType(), metaData.getFieldName(),
								metaData.getFieldOrder()));
				metaList.remove(metaData);
			}
		}

		if (metaList != null) {
			for (MetaData metaData : metaList) {
				documentMetaDTO.getAllMetaDataList().add(
						new MetaDataDTO(metaData.getObjid(), metaData.getFieldId(), metaData.getFieldType(), metaData.getFieldName(),
								metaData.getFieldOrder()));
			}
		}

		return documentMetaDTO;
	}

	@Override
	@Transactional
	public void saveDocMetaDataList(DocMetaSaveDTO dto) {
		List<MetaData> metaDataList = documentMetaDAO.loadMetaDataByDocTypeOid(dto.getDocTypeOid());

		if (metaDataList != null) {
			// silinmis olanlar tespit ediliyor
			for (MetaData metaData : metaDataList) {
				boolean isDeleted = true;
				if (dto.getDocReleatedMetaList() != null) {
					for (MetaDataDTO metaDataDTO : dto.getDocReleatedMetaList()) {
						if (metaDataDTO.getObjid().equals(metaData.getObjid())) {
							isDeleted = false;
							break;
						}
					}
				}
				if (isDeleted) {
					documentMetaDAO.deleteByDocAndMeta(dto.getDocTypeOid(), metaData.getObjid());
				}
			}
		}
		if (dto.getDocReleatedMetaList() != null) {
			// yeni eklenmisler db insert ediliyor
			for (MetaDataDTO metaDataDTO : dto.getDocReleatedMetaList()) {
				boolean isNew = true;
				if (metaDataList != null) {
					for (MetaData metaData : metaDataList) {
						if (metaDataDTO.getObjid().equals(metaData.getObjid())) {
							isNew = false;
							break;
						}
					}
				}
				if (isNew) {
					MetaData metaData = metaDataDAO.findByOid(metaDataDTO.getObjid());
					DocumentType documentType = documentTypeDAO.findByOid(dto.getDocTypeOid());
					DocumentMetaData documentMetaData = new DocumentMetaData(documentType, metaData);
					documentMetaDAO.persistOrUpdate(documentMetaData);
				}
			}
		}
	}

	@Override
	public List<ListItem> loadDocClassCombo(String string) throws Exception {
		return documentTypeDAO.loadDocumentClassCombo();
	}

	@Override
	public List<DocTypeDTO> loadDocTypeList(String docClassOid) {
		List<DocumentType> typeList = documentTypeDAO.loadDocTypeListByParentOid(docClassOid);
		if (typeList == null)
			return null;
		List<DocTypeDTO> typeDtoList = new ArrayList<DocTypeDTO>();
		for (DocumentType type : typeList) {
			typeDtoList.add(new DocTypeDTO(type.getObjid(), type.getParentDocument().getObjid(), type.getName()));
		}
		return typeDtoList;
	}

	@Override
	public void saveDocType(DocTypeDTO dto) {
		DocumentType documentType = null;
		// control is update
		if (!StringUtils.isEmpty(dto.getObjid())) {
			documentType = documentTypeDAO.findByOid(dto.getObjid());
		}
		if (documentType == null)
			documentType = new DocumentType();

		documentType.setParentDocument(documentTypeDAO.findByOid(dto.getDocClassOid()));
		documentType.setObjid(dto.getObjid());
		documentType.setName(dto.getDocTypeName());
		documentTypeDAO.persistOrUpdate(documentType);
	}

	@Override
	public List<ListItem> loadDocTypeCombo(String docClassOid) {
		return documentTypeDAO.loadDocTypeComboByParentOid(docClassOid);
	}

	@Override
	public List<MetaDataDTO> loadMeataWidgetByDocType(String docTypeOid) {
		List<MetaData> metaDataList = documentMetaDAO.loadMetaWithParamByDocTypeOid(docTypeOid);

		List<MetaDataDTO> metaDtoList = new ArrayList<MetaDataDTO>();
		for (MetaData metaData : metaDataList) {
			MetaDataDTO metaDTO = new MetaDataDTO(metaData.getObjid(), metaData.getFieldId(), metaData.getFieldType(),
					metaData.getFieldName(), metaData.getFieldOrder());
			// type combo olup parametre tanimliysa
			if (metaData.getMetaDataParamList() != null) {
				List<MetaParamDTO> metaParamList = new ArrayList<MetaParamDTO>();
				for (MetaDataParam metaParam : metaData.getMetaDataParamList()) {
					metaParamList.add(new MetaParamDTO(metaParam.getObjid(), metaData.getObjid(), metaParam.getParamKey(), metaParam
							.getParamValue()));
				}
				metaDTO.setMetaParamList(metaParamList);
			}
			// metadatadto ekleniyor
			metaDtoList.add(metaDTO);
		}
		return metaDtoList;
	}
}
